home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 18.3 KB | 684 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: SLWinDIB.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWOS.hpp"
-
- #ifdef FW_BUILD_WIN
-
- #ifndef SLWINDIB_H
- #include "SLWinDIB.h"
- #endif
-
- #ifndef SLPRIMEM_H
- #include "SLPriMem.h"
- #endif
-
- #ifndef FWBITMAP_H
- #include "FWBitmap.h"
- #endif
-
- #ifndef FWSTRMRW_H
- #include "FWStrmRW.h"
- #endif
-
- #ifndef FWCOLOR_H
- #include "FWColor.h"
- #endif
-
- //========================================================================================
- // Local helper functions
- //========================================================================================
-
- const unsigned long kWinBitmapFileSignature = 0x4D42; // "BM"
-
- static unsigned long RoundToDWord(unsigned long number)
- {
- return ((number + 31) & (~31)) / 8;
- }
-
- //----------------------------------------------------------------------------------------
- // InitBitmapHeader
- //----------------------------------------------------------------------------------------
-
- static void InitBitmapHeader(BITMAPINFOHEADER& header, int width, int height, int bitDepth)
- {
- header.biSize = sizeof(BITMAPINFOHEADER);
- header.biWidth = width;
- header.biHeight = height;
- header.biPlanes = 1;
- header.biBitCount = bitDepth;
- header.biCompression = BI_RGB;
- header.biSizeImage = 0;
- header.biXPelsPerMeter = 0;
- header.biYPelsPerMeter = 0;
- header.biClrUsed = 0;
- header.biClrImportant = 0;
- }
-
- //========================================================================================
- // Device independent bitmap
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_DIBGetPixelBuffer
- //----------------------------------------------------------------------------------------
-
- FW_WinPixelBufferPtr
- SL_API FW_DIBGetPixelBuffer(FW_WinDIB dib)
- {
- unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
- return (FW_WinPixelBufferPtr) ((char*) dib + paletteSize + dib->bmiHeader.biSize);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBAcquireColorTable
- //----------------------------------------------------------------------------------------
-
- unsigned short
- SL_API FW_PrivDIBAcquireColorTable(FW_WinDIB dib, FW_SColor** colors)
- {
- short colorCount = (short) dib->bmiHeader.biClrImportant;
-
- if (colorCount == 0)
- colorCount = (short) dib->bmiHeader.biClrUsed;
-
- if (colorCount == 0)
- colorCount = dib->bmiHeader.biBitCount == 8 ? 256 : 0;
-
- FW_SColor* colorTable = 0;
- if (colorCount != 0)
- {
- colorTable = (FW_SColor*) FW_PrimitiveAllocateBlock(sizeof(FW_SColor) * colorCount);
- if (colorTable != 0)
- for(short i = 0; i < colorCount; ++ i)
- colorTable[i] = FW_WinRGBQuadToColor(dib->bmiColors + i);
- }
-
- *colors = colorTable;
- return colorCount;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_DIBReleaseColorTable
- //----------------------------------------------------------------------------------------
-
- void
- SL_API FW_DIBReleaseColorTable(FW_SColor* colors)
- {
- FW_PrimitiveFreeBlock(colors);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBConvertToBitmap
- //----------------------------------------------------------------------------------------
-
- HBITMAP
- SL_API FW_PrivDIBConvertToBitmap(FW_WinDIB dib, HPALETTE hPal)
- {
- // we will use the screen device as the source for color depth information
- HDC dc = ::GetDC(NULL);
-
- // select the palette, if any
- HPALETTE hPalOld = NULL;
- if (hPal != NULL)
- {
- hPalOld = ::SelectPalette(dc, hPal, FALSE);
- ::RealizePalette(dc);
- }
-
- // get the pixel buffer and perform the conversion
- FW_WinPixelBufferPtr pixelBuffer = FW_DIBGetPixelBuffer(dib);
- HBITMAP bitmapHandle = ::CreateDIBitmap(dc, &dib->bmiHeader, CBM_INIT, pixelBuffer, dib, DIB_RGB_COLORS);
-
- // clean up
- if (hPalOld != NULL)
- ::SelectPalette(dc, hPalOld, TRUE);
-
- ::ReleaseDC(NULL, dc);
-
- return bitmapHandle;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBConvertFromBitmap
- //----------------------------------------------------------------------------------------
-
- FW_WinDIB
- SL_API FW_PrivDIBConvertFromBitmap(HBITMAP bitmapHandle, short bitDepth, HPALETTE hPal)
- {
- BITMAPINFOHEADER bmiHeader;
-
- // get information about the DDB
- BITMAP bitmapInfo;
- ::GetObject(bitmapHandle, sizeof(bitmapInfo), &bitmapInfo);
-
- // Determine bit depth
- if(bitDepth == 0)
- bitDepth = bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel;
-
- FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8 || bitDepth == 16 || bitDepth == 24);
-
- // Initilaize the header
- InitBitmapHeader(bmiHeader, bitmapInfo.bmWidth, bitmapInfo.bmHeight, bitDepth);
-
- // allocate memory for the header and the palette
- unsigned long colorCount = (bitDepth <= 8) ? 1 << bitDepth : 0;
- unsigned long paletteSize = colorCount * sizeof RGBQUAD;
- unsigned long memSize = bmiHeader.biSize + paletteSize;
- FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(memSize);
- if (dib != 0)
- {
- // stick the header in
- dib->bmiHeader = bmiHeader;
-
- // get image size from the video driver, by calling GetDIBits with NULL
- // parameter for the storage
- HDC hdc = ::GetDC(NULL);
- HPALETTE hPalOld = NULL;
- if (hPal != NULL)
- {
- hPalOld = ::SelectPalette(hdc, hPal, FALSE);
- ::RealizePalette(hdc);
- }
-
- ::GetDIBits(hdc, bitmapHandle, 0, dib->bmiHeader.biHeight, NULL, dib, DIB_RGB_COLORS);
-
- // stick the header in
- dib->bmiHeader = bmiHeader;
-
- // for RGB bitmaps, it is valid for biSizeImage can be 0
- if (bmiHeader.biSizeImage == 0)
- {
- bmiHeader.biSizeImage = RoundToDWord(bitmapInfo.bmWidth *
- bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel) * bitmapInfo.bmHeight;
- }
-
- // reallocate the buffer to hold the bits
- memSize = bmiHeader.biSize + paletteSize + bmiHeader.biSizeImage;
- dib = (FW_WinDIB) FW_PrimitiveResizeBlock(dib, memSize);
- if (dib != 0)
- {
- // now get the bits by calling GetDIBits again, this time with a non-NULL pixel buffer
- FW_WinPixelBufferPtr pixelBuffer = FW_DIBGetPixelBuffer(dib);
- ::GetDIBits(hdc, bitmapHandle, 0, dib->bmiHeader.biHeight, pixelBuffer, dib, DIB_RGB_COLORS);
- }
-
- // clean up the palette
- if (hPalOld != NULL)
- {
- ::SelectPalette(hdc, hPalOld, FALSE);
- ::RealizePalette(hdc);
- }
- ::ReleaseDC(NULL, hdc);
- }
-
- return dib;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_DIBGetPaletteSize
- //----------------------------------------------------------------------------------------
-
- unsigned long
- SL_API FW_DIBGetPaletteSize(FW_WinDIB dib)
- {
- short numColors = (short) dib->bmiHeader.biClrUsed;
- short bits = dib->bmiHeader.biBitCount;
-
- if(numColors == 0)
- {
- switch(bits)
- {
- case 1:
- numColors = 2;
- break;
- case 4:
- numColors = 16;
- break;
- case 8:
- numColors = 256;
- break;
- default:
- numColors = 0;
- break;
- }
- }
-
- return sizeof(RGBQUAD) * numColors;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBGetPalette
- //----------------------------------------------------------------------------------------
-
- HPALETTE
- SL_API FW_PrivDIBGetPalette(Environment* ev, FW_WinDIB dib)
- {
- // It only makes sense to support palettes for 8-bit DIBs.
- // Note that I check ClrImportant and ClrUsed which
- // both may be set in HiColor or TrueColor DIBs.
-
- short colorCount = (short) dib->bmiHeader.biClrImportant;
-
- if (colorCount == 0)
- colorCount = (short) dib->bmiHeader.biClrUsed;
-
- if (colorCount == 0)
- colorCount = dib->bmiHeader.biBitCount == 8 ? 256 : 0;
-
- RGBQUAD* colorTable = dib->bmiColors;
-
- // Create a palette
- HPALETTE hPal = NULL;
- if (colorCount != 0)
- {
- struct SPal
- {
- WORD palVersion;
- WORD palNumEntries;
- PALETTEENTRY palEntry[256];
- };
-
- SPal logpal;
-
- logpal.palVersion = 0x300;
- logpal.palNumEntries = colorCount;
-
- for (short i = 0; i < colorCount; ++ i, ++ colorTable)
- {
- logpal.palEntry[i].peRed = colorTable->rgbRed;
- logpal.palEntry[i].peGreen = colorTable->rgbGreen;
- logpal.palEntry[i].peBlue = colorTable->rgbBlue;
- logpal.palEntry[i].peFlags = 0;
- }
-
- hPal = ::CreatePalette((LOGPALETTE*)&logpal);
- if (hPal == 0)
- FW_SetEvError(ev, FW_xMemoryExhausted);
- }
-
- return hPal;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBCreate
- //----------------------------------------------------------------------------------------
-
- FW_WinDIB
- SL_API FW_PrivDIBCreate(
- short bitDepth, short width, short height,
- short nbColors, const FW_SColor* colorTable,
- const void* pixels)
- {
- FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8);
-
- // Calculate the sizes
- unsigned short colorCount = 1 << bitDepth;
- unsigned long paletteSize = colorCount * sizeof(RGBQUAD);
- unsigned long imageSize = RoundToDWord(width * bitDepth) * height;
- unsigned long size = sizeof(BITMAPINFOHEADER) + paletteSize + imageSize;
-
- FW_ASSERT(nbColors <= colorCount);
-
- // Allocate DIB memory
- FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(size);
- if (dib != 0)
- {
- // Initiliaze the header
- InitBitmapHeader(dib->bmiHeader, width, height, bitDepth);
- dib->bmiHeader.biClrImportant = nbColors;
-
- // Copy the color table
- for(int i = 0; i < nbColors; ++ i)
- FW_WinColorToRGBQuad(colorTable[i], dib->bmiColors + i);
-
- // Clear the remaining colors
- if(nbColors != colorCount)
- memset(dib->bmiColors + nbColors, 0, sizeof(RGBQUAD) * (colorCount - nbColors));
-
- // Copy the bits
- if(pixels != NULL)
- {
- FW_WinPixelBufferPtr pixelBuffer = FW_DIBGetPixelBuffer(dib);
- FW_PrimitiveCopyMemory(pixels, pixelBuffer, imageSize);
- }
- }
-
- return dib;
- }
-
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBCreateCopy
- //----------------------------------------------------------------------------------------
-
- FW_WinDIB
- SL_API FW_PrivDIBCreateCopy(FW_WinDIB dib)
- {
- FW_ASSERT(dib != NULL);
-
- unsigned long headerSize = dib->bmiHeader.biSize;
- unsigned long imageSize = dib->bmiHeader.biSizeImage;
-
- unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
- unsigned long fullSize = paletteSize + headerSize + imageSize;
-
- FW_WinDIB dibCopy = (FW_WinDIB) FW_PrimitiveAllocateBlock(fullSize);
- if (dibCopy != 0)
- FW_PrimitiveCopyMemory(dib, dibCopy, fullSize);
-
- return dibCopy;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBLoadFromStream
- //----------------------------------------------------------------------------------------
-
- FW_WinDIB SL_API
- FW_PrivDIBLoadFromStream(
- Environment* ev,
- FW_HReadableStream hStream,
- FW_Boolean bFileHeader)
- {
- FW_SOM_TRY
- {
- FW_CReadableStream stream(hStream);
-
- // read the header first
- if (bFileHeader)
- {
- BITMAPFILEHEADER bmfh;
- stream.Read((void*) &bmfh, sizeof(bmfh));
-
- // verify the header
- if(bmfh.bfType != kWinBitmapFileSignature)
- {
- FW_SetEvError(ev, FW_xInvalidBitmapData);
- return 0;
- }
- }
-
- // Read the DIB header
- FW_Boolean bIsWindowsBitmap;
- int headerSize;
-
- BITMAPINFOHEADER bmih;
-
- stream.Read((void*) &bmih.biSize, sizeof(bmih.biSize));
-
- if(bmih.biSize == sizeof(BITMAPINFOHEADER)) // Windows bitmap
- {
- stream.Read((void*) &bmih.biWidth, sizeof(bmih) - sizeof(bmih.biSize));
- bIsWindowsBitmap = TRUE;
- headerSize = sizeof(bmih);
- }
- else if(bmih.biSize == sizeof(BITMAPCOREHEADER)) // OS/2 bitmap
- {
- BITMAPCOREHEADER bmch;
- bmch.bcSize = bmih.biSize;
- stream.Read((void* )&bmch.bcWidth, sizeof(bmch) - sizeof(bmch.bcSize));
- bIsWindowsBitmap = FALSE;
-
- // Fake a Windows DIB header from the OS/2 one
- bmih.biSize = sizeof(BITMAPINFOHEADER);
- bmih.biWidth = bmch.bcWidth;
- bmih.biHeight = bmch.bcHeight;
- bmih.biPlanes = 1;
- bmih.biBitCount = bmch.bcBitCount;
- bmih.biCompression = 0;
- bmih.biSizeImage = 0; // For now
- bmih.biXPelsPerMeter = 0;
- bmih.biYPelsPerMeter = 0;
- bmih.biClrUsed = 0;
- bmih.biClrImportant = 0;
-
- headerSize = sizeof(bmch);
- }
- else
- {
- FW_SetEvError(ev, FW_xMemoryExhausted);
- return 0;
- }
-
- // Determine the image size
- if (bmih.biSizeImage == 0)
- bmih.biSizeImage = bmih.biHeight * RoundToDWord(bmih.biWidth * bmih.biBitCount);
-
- // Determine the palette size
- int colorCount = (bmih.biBitCount <= 8) ? (1 << bmih.biBitCount) : 0;
- short paletteSize = colorCount * sizeof (RGBQUAD);
-
- // Allocate memory for the DIB
- FW_WinDIB dib = (FW_WinDIB) FW_PrimitiveAllocateBlock(sizeof(BITMAPINFOHEADER) + paletteSize + bmih.biSizeImage);
- if (dib == 0)
- {
- FW_SetEvError(ev, FW_xInvalidBitmapData);
- return 0;
- }
-
- dib->bmiHeader = bmih;
-
- // Read the palette
- RGBQUAD* palettePtr = dib->bmiColors;
- if (colorCount != 0)
- {
- stream.Read(palettePtr, colorCount * sizeof RGBQUAD);
- }
- else
- {
- RGBTRIPLE rgbt[256];
- stream.Read(rgbt, colorCount * sizeof RGBTRIPLE);
- for (short n = 0; n < colorCount; ++ n)
- {
- palettePtr[n].rgbRed = rgbt[n].rgbtRed;
- palettePtr[n].rgbGreen = rgbt[n].rgbtGreen;
- palettePtr[n].rgbBlue = rgbt[n].rgbtBlue;
- palettePtr[n].rgbReserved = 0;
- }
- }
-
- // Read the bits
- void* bitsPtr = (char*) palettePtr + colorCount * sizeof(RGBQUAD);
- stream.Read(bitsPtr, bmih.biSizeImage);
-
- return dib;
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDIBSaveToStream
- //----------------------------------------------------------------------------------------
-
- void
- SL_API FW_PrivDIBSaveToStream(
- Environment* ev,
- FW_HWritableStream hStream,
- FW_WinDIB dib,
- FW_Boolean bFileHeader)
- {
- FW_SOM_TRY
- {
- FW_CWritableStream stream(hStream);
-
- unsigned long headerSize = dib->bmiHeader.biSize;
- unsigned long imageSize = dib->bmiHeader.biSizeImage;
-
- // calculate file size and image offset
- unsigned long paletteSize = FW_DIBGetPaletteSize(dib);
- unsigned long fullSize = paletteSize + headerSize + imageSize;
-
- // Write the file header
- if(bFileHeader)
- {
- BITMAPFILEHEADER bmfh;
- bmfh.bfType = kWinBitmapFileSignature;
- bmfh.bfSize = fullSize + sizeof(BITMAPFILEHEADER);
- bmfh.bfReserved1 = 0;
- bmfh.bfReserved2 = 0;
- bmfh.bfOffBits = paletteSize + headerSize + sizeof(BITMAPFILEHEADER);
-
- stream.Write((void*) &bmfh, sizeof(BITMAPFILEHEADER));
- }
-
- // Write the bits
- stream.Write((void*) dib, fullSize);
- }
- FW_SOM_CATCH
- }
-
- //----------------------------------------------------------------------------------------
- // FW_DIBFree
- //----------------------------------------------------------------------------------------
-
- void
- SL_API FW_DIBFree(FW_WinDIB dib)
- {
- FW_CMemoryManager::FreeBlock(dib);
- }
-
- //========================================================================================
- // Device dependent bitmap
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_DDBGetColorDepth
- //----------------------------------------------------------------------------------------
-
- short
- SL_API FW_DDBGetColorDepth(HBITMAP hBitmap)
- {
- BITMAP bm;
- ::GetObject(hBitmap, sizeof(bm), &bm);
-
- if(bm.bmPlanes != 1)
- return bm.bmPlanes;
-
- return bm.bmBitsPixel;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_DDBCopyImage
- //----------------------------------------------------------------------------------------
-
- void
- SL_API FW_DDBCopyImage(
- HBITMAP hBmpDst,
- HPALETTE hPalDst,
- const RECT* rectDst,
- HBITMAP hBmpSrc,
- HPALETTE hPalSrc,
- const RECT* rectSrc,
- short options)
- {
- FW_ASSERT(hBmpSrc != NULL);
- FW_ASSERT(hBmpDst != NULL);
-
- HDC hDCDst = ::CreateCompatibleDC(NULL);
- HDC hDCSrc = ::CreateCompatibleDC(NULL);
-
- if(hDCDst != NULL && hDCSrc != NULL)
- {
- HBITMAP hBmpDstOld = (HBITMAP) ::SelectObject(hDCDst, hBmpDst);
- HBITMAP hBmpSrcOld = (HBITMAP) ::SelectObject(hDCSrc, hBmpSrc);
-
- if(hBmpDstOld != NULL && hBmpSrcOld != NULL)
- {
- // Select the palettes
- HPALETTE hPalOldDst = NULL;
- if (hPalDst != NULL)
- {
- hPalOldDst = ::SelectPalette(hDCDst, hPalDst, FALSE);
- ::RealizePalette(hDCDst);
- }
-
- HPALETTE hPalOldSrc = NULL;
- if (hPalSrc != NULL)
- {
- hPalOldSrc = ::SelectPalette(hDCSrc, hPalSrc, FALSE);
- ::RealizePalette(hDCSrc);
- }
-
- if(options == FW_kScaleImage)
- {
- // Stretch the bits
- ::StretchBlt(
- hDCDst,
- rectDst->left, rectDst->top,
- rectDst->right - rectDst->left, rectDst->bottom - rectDst->top,
- hDCSrc,
- rectSrc->left, rectSrc->top,
- rectSrc->right - rectSrc->left, rectSrc->bottom - rectSrc->top,
- SRCCOPY);
- }
- else
- {
- // Determine the size of image we can copy
- long copyWidth = rectSrc->right - rectSrc->left;
- if(copyWidth > rectDst->right - rectDst->left)
- copyWidth = rectDst->right - rectDst->left;
-
- long copyHeight = rectSrc->bottom - rectSrc->top;
- if(copyHeight > rectDst->bottom - rectDst->top)
- copyHeight = rectDst->bottom - rectDst->top;
-
- // Copy the bits
- ::BitBlt(
- hDCDst,
- rectDst->left, rectDst->top,
- copyWidth, copyHeight,
- hDCSrc,
- rectSrc->left, rectSrc->top,
- SRCCOPY);
-
- // Erase any space to the right of the copied image piece
- if(copyWidth < rectDst->right - rectDst->left)
- ::PatBlt(
- hDCDst,
- rectDst->left + copyWidth,
- rectDst->top,
- rectDst->right - rectDst->left - copyWidth,
- rectDst->bottom - rectDst->top,
- WHITENESS);
-
- // Erase any space to the bottom of the copied image piece
- if(copyHeight < rectDst->bottom - rectDst->top)
- ::PatBlt(
- hDCDst,
- rectDst->left,
- rectDst->top + copyHeight,
- rectDst->right - rectDst->left,
- rectDst->bottom - rectDst->top - copyHeight,
- WHITENESS);
- }
-
- // Clean up the palettes
- if (hPalOldDst != NULL)
- ::SelectPalette(hDCDst, hPalOldDst, FALSE);
-
- if (hPalOldSrc != NULL)
- ::SelectPalette(hDCSrc, hPalOldSrc, FALSE);
- }
-
- if(hBmpDstOld != NULL)
- ::SelectObject(hDCDst, hBmpDstOld);
-
- if(hBmpSrcOld != NULL)
- ::SelectObject(hDCSrc, hBmpSrcOld);
- }
-
- if(hDCDst != NULL)
- ::DeleteDC(hDCDst);
-
- if(hDCSrc != NULL)
- ::DeleteDC(hDCSrc);
- }
-
- #endif
-